/*
 * platform_uc.cpp
 *
 *  Created on: Dec 27, 2013
 *      Author: killerg
 */


#include "../bill_deps.h"
#include "platform_deps.h"

#include <list>
#include <map>
#include <string>

static const char* apiKey = "52edb3cfe5104ed1d8d7b9cb2bcb0a90";
static const int cpId = 32838;
static const int gameId = 537117;

static void send_query(
        http_server::p_request req,
        int id,
        int code,
        const char* msg,
        std::pair<std::string, std::string>* role = NULL) {

    Json::Value ret;
    ret["id"] = id;

    ret["state"]["code"] = code;
    ret["state"]["msg"] = msg;

    Json::Value &rolelist = ret["rolelist"];
    if (NULL != role) {
        Json::Value ii_json;
        ii_json["roleid"] = role->first;
        ii_json["rolename"] = role->second;
        rolelist.append(ii_json);
    }

    req->send_reply(200, to_cstr(ret));
}

static void send_bill(http_server::p_request req, const char* why = NULL) {
	if (NULL == why) {
		req->send_reply(200, "SUCCESS");
	} else {
		req->send_reply(200, "FAILURE");
        char buff[100];
        time_t now = time(NULL);
        strftime(buff,100,"%Y%m%d_%H%M%S",localtime(&now));
    	UTIL_LOG(E, "%s EPI_uc msg:%s body:%s", buff, why, req->body.c_str());
	}
}

bool init_uc() {
    g_https->handle("/bill/uc", [](http_server::p_request req){
    	if (g_svrmgr->db_set >= 100) {
        	send_bill(req, "need retry");
        	return;
    	}

    	const Json::Value req_json = to_json(req->body);
        if (req->body.empty() || !req_json.isObject()) {
        	send_bill(req, "nobody");
            return;
        }

        const Json::Value &data_json = req_json["data"];
        if (!data_json.isObject()) {
        	send_bill(req, "invalid data");
            return;
        }

        string orderStatus =  data_json.get("orderStatus", "F").asCString();
        if (orderStatus != "S") {
            send_bill(req);
            return;
        }

        map<string, string> tosign;
        for (auto itr = data_json.begin(); itr != data_json.end(); ++itr) {
            string key = itr.key().asCString();
            if (key == "intfType") {
                if ((*itr).isInt()) {
                    tosign[key] = fmt_cstr("%d", (*itr).asInt());
                }
            } else {
                if ((*itr).isString())
                    tosign[key] = (*itr).asCString();
            }
        }

        stringstream ss;
        ss << cpId;
        for (const auto &p : tosign) {
            ss << p.first << "=" << p.second;
        }
        ss << apiKey;
        string calced_sign = Md5(ss.str().c_str());
        string sign = req_json.get("sign", "").asString();
        if (sign.empty() || calced_sign != sign) {
        	send_bill(req, "err sign");
            return;
        }

        int gameId = atoi(data_json.get("gameId", "-1").asCString());
        if (gameId < 0 || gameId != ::gameId) {
        	send_bill(req, "err gameId");
            return;
        }

        string account;
        string orderId;
        double payFee = 0;
        int serverid = -1;
        string machinecode;

        if (data_json["ucid"].isString()) {
            string ucid = data_json["ucid"].asCString();
            account = fmt_cstr("uc-%s", ucid.c_str());
        }
        if (data_json["orderId"].isString()) {
            orderId = fmt_cstr("uc-%s", data_json["orderId"].asCString());
        }
        if (data_json["amount"].isString()) {
            payFee = atof(data_json["amount"].asCString()) * g_cfg->Rate;
        }

        if (data_json["callbackInfo"].isString()) {
            std::vector<std::string> vNote;
            split(data_json["callbackInfo"].asString(), ",", vNote);
    		if (vNote.size() != 2) {
    			send_bill(req, "err callbackInfo");
                return;
    		}
    		serverid = atoi(vNote[0].c_str());
    		machinecode = vNote[1];
        }

        if (account.empty() || orderId.empty() || payFee <= 0 || serverid < 0) {
        	send_bill(req, "invalid arg");
            return;
        }

        auto playerinfo = g_svrmgr->get_player_info(serverid, account);
        if (NULL == playerinfo) {
        	send_bill(req, "no player info");
            return;
        }

        g_svrmgr->post_order(serverid, orderId, playerinfo->playerid, payFee, machinecode, [req](bool ok){
            if (ok)
            	send_bill(req);
            else
            	send_bill(req, "err post order");
        });

    });

    g_https->handle("/query/uc", [](http_server::p_request req){
        const Json::Value req_json = to_json(req->body);

        int id = req_json.get("id", -1).asInt();

        if (req->body.empty() || !req_json.isObject()) {
            send_query(req, id, -1, "no body or body invalid json");
            return;
        }

        const Json::Value &data_json = req_json["data"];
        if (!data_json.isObject()) {
            send_query(req, id, -1, "invalid data");
            return;
        }

        int gameId = data_json.get("gameId", -1).asInt();
        int serverId = data_json.get("serverId", -1).asInt();
        int ucid = data_json.get("ucid", -1).asInt();

        if (gameId < 0 || serverId < 0 || ucid < 0) {
            send_query(req, id, -1, "one of gameId serverId ucid is invalid");
            return;
        }

        string calced_sign = Md5(fmt_cstr("%dgameId=%dserverId=%ducid=%d%s", cpId, gameId, serverId, ucid, apiKey));
        if (calced_sign != req_json["sign"].asString()) {
            send_query(req, id, -1, "invalid sign");
            return;
        }

        auto playerinfo = g_svrmgr->get_player_info(serverId, fmt_cstr("uc-%d", ucid));
        if (NULL == playerinfo) {
            send_query(req, id, -1, "no player info");
            return;
        }

        auto role = std::make_pair(fmt_str("%d", playerinfo->playerid), playerinfo->playername);
        send_query(req, id, 1, "ok", &role);
    });
    return true;
}
